/*-
 * Copyright (C) 2020, Shanghai Trusted Industry Control Platform Co., Ltd.
 * Created by 周正辉 (Zhenghui Zhou) <zhouzhenghui@ticpsh.com>
 */

#ifndef DEPENDENCY_GRAPH_H
#define DEPENDENCY_GRAPH_H

#include <clang/Basic/FileManager.h>
#include <clang/Lex/PPCallbacks.h>
#include <clang/Lex/Preprocessor.h>

#include <nlohmann/json.hpp>

namespace rocket {
namespace testif {

/**
 * Find the dependencies using clang::PPCallback interface.
 */
class DependencyGraph : public clang::PPCallbacks {
 public:
  DependencyGraph(nlohmann::json& includes, const clang::Preprocessor& pp,
                  const std::string& main_file, const std::string& sysroot);
  void InclusionDirective(clang::SourceLocation hash_loc,
                          const clang::Token& include_token,
                          llvm::StringRef filename, bool is_angled,
                          clang::CharSourceRange filename_range,
                          const clang::FileEntry* file,
                          llvm::StringRef search_path,
                          llvm::StringRef relative_path,
                          const clang::Module* imported,
                          clang::SrcMgr::CharacteristicKind file_type);

 private:
  clang::SourceManager& src_mgr;
  nlohmann::json& missing;
  nlohmann::json& files;
  std::string main_file;
  std::string sysroot;
  std::string root;
  void addDependencyLocation(nlohmann::json& froms,
                             clang::SourceLocation hash_loc,
                             clang::CharSourceRange filename_range);
  std::string makeCanonicalPath(const clang::FileEntry* file);
};

}  // namespace testif
}  // namespace rocket

#endif
